home account info subscribe login search FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
To access the contents, click the chapter and section titles.

Bug Proofing Visual Basic: A Guide to Error Handling and Prevention
(Publisher: John Wiley & Sons, Inc.)
Author(s): Rod Stephens
ISBN: 0471323519
Publication Date: 11/01/98

Search this book:
 
Previous Table of Contents Next


The previous example also uses a numeric value to define a time interval. It should use the DateAdd function to be more obvious. Mixing numeric and date functions is confusing and relies on the specific implementation of date variables. The following code shows a better way to handle this problem.

Private Sub RoundoffProblem()
Dim i As Integer
Dim the_time As Date

    the_time = CDate(“1:00 am”)
    For i = 0 To 3
        ‘ Do something with the_time.
             :

        ‘ Add 20 minutes to the_time.
        the_time = DateAdd(“n”, 20, the_time)
    Next i
End Sub

This code executes the statements within the For loop four times as desired. Unfortunately, using the DateAdd function is significantly slower than adding floating-point numbers. Even so, this version is much easier to understand so you should use it instead of the previous version. Few programs perform so many date calculations that this kind of loop dominates the program’s runtime, so the slightly reduced performance is more than offset by the improved readability.

Don’t Resize Inside Loops

Do not change the size of an array or collection while you are iterating over its members. The following code, for example, is meant to remove the odd values from a collection. Unfortunately, Visual Basic calculates the stopping value numbers.Count only when it enters the For loop. As items are removed from the collection, the loop’s stopping value does not change even though the number of items in the collection does. If the program removes any items, the index i will eventually run past the collection’s ever-decreasing upper bound and the program will crash with a subscript out of range error.

The For loop also increases i even when an item is removed. If the routine removes the first item, the second becomes the new first item. Then i is increased to 2, so the code never examines the new first item, which was the old second item.

Dim numbers As New Collection
Dim i As Integer
        :
    ‘ Initialize the collection.
        :
    ‘ Remove the odd numbers.
    For i = 1 To numbers.Count
        If numbers(i) Mod 2 = 1 Then numbers.Remove i
    Next i

The following code shows one correct method for removing the collection’s odd entries. The While loop calculates the continuing condition i <= numbers.Count every time the loop is executed so it can determine when i exceeds the collection’s current upper bound. The While loop also allows the program to explicitly determine when to increment i. The code increases i only when it does not remove an item, so it can consider every item in the collection.

Dim numbers As New Collection
Dim i As Integer
        :
    ‘ Initialize the collection.
        :
    ‘ Remove the even numbers.
    i = 1
    Do While i <= numbers.Count
        If numbers(i) Mod 2 = 1 Then
            ‘ Remove this item.
            numbers.Remove i
        Else
            ‘ Consider the next item.
            i = i + 1
        End If
Loop

Watch for Circular References

Visual Basic performs automatic reference counting. When you create an object, Visual Basic keeps track of the number of variables referencing that object. If the reference count ever reaches 0, the system knows that the program can no longer access the object, so Visual Basic automatically destroys it. The following code illustrates how the system performs reference counting.

Dim obj1 As MyObject        ‘ Initially these references do not point
Dim obj2 As MyObject        ‘     to any objects.

    Set obj1 = New MyObject ‘ Create an object.               Count = 1.
    Set obj2 = obj1         ‘ obj2 also points to the object. Count = 2.
    Set obj1 = Nothing      ‘ Only obj2 points to the object. Count = 1.
    Set obj2 = Nothing      ‘ Nothing points to the object.   Count = 0.

Suppose the program creates a Cell object that has a public NextCell variable that is itself a reference to another Cell object. Suppose the program sets the cell’s NextCell pointer to reference itself.

Dim new_cell As New Cell

    Set new_cell.NextCell = new_cell
    Set new_cell = Nothing

Because this object contains a reference to itself, its reference count is not 0, even after the variable new_cell is set to Nothing. The Cell object that new_cell was pointing to still points to itself, so its reference count is 1 and Visual Basic cannot destroy it.

Similarly, a program could build a long chain of cells with the last cell pointing to the first. Both of these situations are reference loops. As long as the items in the loop refer to each other, Visual Basic cannot free any of them. The program must explicitly set some of the references to Nothing before the system can free the memory.

Beware of this kind of reference loop. In more complex data structures like trees, networks, and graphs, reference loops can be much harder to detect and remove. Reference loops are one of the few ways a Visual Basic program can permanently lose memory.

Understand Form Lifetime

The lifetime of a form can be confusing. Accessing the values and variables defined by the form can cause behavior you may find strange.

Like other objects in Visual Basic, forms are referenced counted. When you unload a form, you remove it from the screen and destroy the controls it contains. The form object is not completely deleted, however, until the program’s last reference to it is set to Nothing. In particular, the variables defined by the form are still available to the program.

For example, the following code creates a form, saves the value 123 in the public ID variable defined in the form’s Declarations section, and sets the text displayed by a TextBox control. It then unloads the form. At that point, the controls on the form have been destroyed. However, the public ID variable is still loaded and still contains the value 123 saved by the program. The following code displays this value and sets frm to Nothing so the form is completely destroyed.

Dim frm As EmployeeForm

    Set frm = New EmployeeForm       ‘ Create the form obect.
    frm.Show                         ‘ Make the form visible.
    frm.ID = 123                     ‘ Set a public variable’s value.
    frm.txtFirstName.Text = “Gomez”  ‘ Set a control’s property.

    Unload frm                       ‘ Unload the form.

    MsgBox frm.ID                    ‘ Display the ID.

    Set frm = Nothing                ‘ Finish destroying the form.

This is confusing enough, but the story gets worse. If you access a control or property on a form that is not loaded, Visual Basic automatically loads it. This is very different from accessing a variable defined by the form.


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-1999 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permision of EarthWeb is prohibited.